package linex

import (
	"encoding/json"
	"fmt"
	"net/http"
	"strings"
)

// 别名 方便转换json
type H map[string]interface{}

type Context struct {
	Writer     http.ResponseWriter // writer
	Req        *http.Request       // request
	Path       string              // request.url.path
	Method     string              // method
	Params     map[string]string   // uri参数
	StatusCode int                 // response status code
	handlers   []HandlerFunc       // 中间件
	index      int                 // 当前执行中间件的索引
}

// 新建 context 方法
func NewContext(w http.ResponseWriter, req *http.Request) *Context {
	return &Context{
		Writer: w,
		Req:    req,
		Path:   strings.ToLower(req.URL.Path),
		Method: req.Method,
		Params: make(map[string]string),
		index:  -1,
	}
}

func (c *Context) Next() {
	c.index++
	l := len(c.handlers)
	for ; c.index < l; c.index++ {
		c.handlers[c.index](c)
	}
}

// 获取 URI 中的参数
func (c *Context) Param(key string) string {
	value, _ := c.Params[key]
	return value
}

// 查询POST FORM中的参数
func (c *Context) PostForm(key string) string {
	return c.Req.FormValue(key)
}

// 查询get中的参数
func (c *Context) Query(key string) string {
	return c.Req.URL.Query().Get(key)
}

// 响应状态码
func (c *Context) Status(code int) {
	c.StatusCode = code
	c.Writer.WriteHeader(code)
}

// 设置头信息
func (c *Context) SetHeader(key, value string) {
	c.Writer.Header().Set(key, value)
}

// 返回string
func (c *Context) String(code int, format string, values ...interface{}) {
	c.SetHeader("Content-Type", "text/plain")
	c.Status(code)
	if _, err := c.Writer.Write([]byte(fmt.Sprintf(format, values...))); err != nil {
		panic(err)
	}
}

// 返回 JSON
func (c *Context) JSON(code int, obj interface{}) {
	c.SetHeader("Content-Type", "application/json")
	c.Status(code)
	encoder := json.NewEncoder(c.Writer)
	if err := encoder.Encode(obj); err != nil {
		http.Error(c.Writer, err.Error(), http.StatusInternalServerError)
	}
}

// 返回 二进制数据
func (c *Context) Data(code int, data []byte) {
	c.Status(code)
	if _, err := c.Writer.Write(data); err != nil {
		panic(err)
	}
}

// 返回 HTML 模板
func (c *Context) HTML(code int, html string) {
	c.SetHeader("Content-Type", "text/html")
	c.Status(code)
	if _, err := c.Writer.Write([]byte(html)); err != nil {
		panic(err)
	}
}
